﻿using System;
using System.Collections;
using System.Collections.Generic;

namespace BizElements.TemplateEngine
{
    /// <summary>Variable meta (name, default value, description) and chosen value.</summary>
    public sealed class TemplateVariableInfo
    {
        #region Constructors.

        /// <summary>Initializes a new instance of <b>TemplateVariableInfo</b> class.</summary>
        public TemplateVariableInfo(string name, string defaultValue, string description)
        {
            this.Name = name;
            this.DefaultValue = defaultValue;
            this.Description = description;
            this.value = defaultValue;
            this.AllowedValues = new NameValuePair[0];
        }

        /// <summary>Initializes a new instance of <b>TemplateVariableInfo</b> class.</summary>
        public TemplateVariableInfo(string name, string defaultValue, string description, NameValuePair[] allowedValues)
        {
            this.Name = name;
            this.DefaultValue = defaultValue;
            this.Description = description;
            this.value = defaultValue;
            this.AllowedValues = allowedValues ?? new NameValuePair[0];
        }

        #endregion

        #region Properties.

        /// <summary>Gets variable name.</summary>
        public string Name { get; private set; }

        /// <summary>Gets default value.</summary>
        public string DefaultValue { get; private set; }

        /// <summary>Gets variable description.</summary>
        public string Description { get; private set; }

        string value;

        /// <summary>Gets or sets variable value.</summary>
        public string Value
        {
            get { return this.value; }
            set
            {
                bool hasChanged = (value != this.value);
                this.value = value;
                if (hasChanged && this.ValueChanged != null)
                    ValueChanged(this, new EventArgs());
            }
        }

        /// <summary>Gets an optional list of allowed value.</summary>
        public NameValuePair[] AllowedValues { get; private set; }

        #endregion

        /// <summary>Occurs when variable value is changed.</summary>
        public event EventHandler ValueChanged;
    }

    /// <summary>Represents a read-only collection of key/value pairs where key represent variable name and value represents TemplateVariableInfo object.</summary>
    public sealed class TemplateVariableCollection : IEnumerable<KeyValuePair<string, TemplateVariableInfo>>
    {
        #region CTor.

        /// <summary>Initializes a new instance of <b>TemplateVariableCollection</b> class.</summary>
        public TemplateVariableCollection(IDictionary<string, TemplateVariableInfo> variables)
        {
            this.variables = variables;
        }

        #endregion

        #region Indexer.

        IDictionary<string, TemplateVariableInfo> variables;

        /// <summary>Tries to get variable with the specified name.</summary>
        /// <param name="name">Variable name.</param>
        public string this[string name]
        {
            get
            {
                TemplateVariableInfo var;
                bool exists = this.variables.TryGetValue(name, out var);
                return (exists) ? var.Value : "";
            }
        }

        #endregion

        #region IEnumerable<KeyValuePair<string,TemplateVariableInfo>> Members

        /// <summary>Returns an enumerator that iterates through the collection.</summary>
        /// <returns>An IEnumerator object that can be used to iterate through the collection.</returns>
        public IEnumerator<KeyValuePair<string, TemplateVariableInfo>> GetEnumerator()
        {
            return this.variables.GetEnumerator();
        }

        #endregion

        #region IEnumerable Members

        /// <summary>Returns an enumerator that iterates through the collection.</summary>
        /// <returns>An IEnumerator object that can be used to iterate through the collection.</returns>
        IEnumerator IEnumerable.GetEnumerator()
        {
            return this.variables.GetEnumerator();
        }

        #endregion
    }    
}